﻿using System;
using System.Collections.Generic;
using System.Text;

public class Packer
{
	public Action OnRequest;
	public Action<RecData> OnCallback;

	private int headLength;
	private BaseSocket Socket;
	public IMsgCenter msgCenter;

	public Packer(BaseSocket s)
	{
		Socket = s;
		headLength = ConstantDef.headLength;
		msgCenter = new MsgCenter();
	}

	/// <summary>	/// <summary>
	/// The list to add Tcp data 
	/// </summary>
	private List<SendData> reqList = new List<SendData>();

	/// Send request
	/// </summary>
	public void Add(SendData tcp) {
		reqList.Add(tcp);
	}

	public void AddRange(IEnumerable<SendData> list) {
		reqList.AddRange(list);
	}

	public void Excute()
	{
		Send();
		msgCenter.ProcessQueue();
	}

	private void Send() {
		if (reqList.Count <= 0) {
			return;
		}

		//正在发送
		SendData data;
		int count = reqList.Count;
		for (int i = 0; i < count; i++) {
			data = reqList[i];
			if (data.IsSending) {
				continue;
			}

			lock (data.AsynLock) {
				data.IsSending = true;

				Socket.Send(ConvetToBuffer(data));
			}

			if (data.NeedWait) {
				if (OnRequest != null) {
					OnRequest();
				}

				//等待此次请求结束，清空请求列表
				break;
			}
		}
		reqList.Clear();
	}

	public void Pack(byte[] bytes)
	{
		RecData data = converToData(bytes);

		msgCenter.EnMsg(data);

		if (data.ReqType.Equals(ReqType.Callback))
		{
			if (OnCallback != null)
			{
				OnCallback(data);
			}
		}
	}

	private byte[] ConvetToBuffer(SendData data)
	{
		byte[] bytes = new byte[data.Length + headLength];
//		MyLog.LogError("Send ID : " + data.ID + " length : " + bytes.Length);
		byte[] headBuffer = BitConverter.GetBytes(data.Length);

		Buffer.BlockCopy(headBuffer, 0, bytes, 0, headBuffer.Length);
		Buffer.BlockCopy(data.SendBuf, 0, bytes, headLength, data.Length);

		return bytes;
	}

	private RecData converToData(byte[] bytes)
	{
		byte[] methodBuffer = new byte[headLength];
		Buffer.BlockCopy(bytes, 0, methodBuffer, 0, headLength);

		short method = BitConverter.ToInt16(methodBuffer, 0);
		bool isCallback = (method & 1 << headLength * 8 - 1) > 0;
		method = (short)(method & ~(1 << headLength * 8 - 1));
		string content = Encoding.UTF8.GetString(bytes, headLength, bytes.Length - headLength);

		RecData data = new RecData(method, content, TcpState.Success);
		data.ReqType = isCallback ? ReqType.Callback : ReqType.None;

		return data;
	}
}
